using System;
using System.Collections.Generic;
using System.Text;
using Goudse.BcVerzekering.InkomenCollectief;
using System.Management;

namespace Goudse.BcVerzekering.InkomenCollectief.CommandLine
{
    class Program
    {
        private static string bts_WMINameSpace = @"root\MicrosoftBizTalkServer";
        private static string bts_ReceiveLocation = "MSBTS_ReceiveLocation";
        private static string bts_SendPort = "MSBTS_SendPort";

        static void Main(string[] args)
        {
            CommandLineParser commandLineParser = new CommandLineParser();
           
            try
            {
                 string choice = string.Empty;
                 try
                 {
                        choice= commandLineParser.getChoice();
                 }
                 catch (Exception)
                 {
                     
                    
                 }
             
                if (commandLineParser.IsCommand("/?", "-?"))
                {
                    ShowHelp();
                }
                else
                {
                    if (commandLineParser.IsCommand("-l", "/l", "-list", "/list"))
                    {
                        if (choice == "-RL" || choice == "-rl")
                        {
                            Console.WriteLine(ListRLWithServiceWindow());
                        }
                        if (choice == "-SP" || choice == "-sp")
                        {
                            Console.WriteLine(ListSPWithServiceWindow());
                        }
                        if (choice == "-SS" || choice == "-ss")
                        {
                            Console.WriteLine(ListSSWithServiceWindow());
                        }
                    }
                    else
                    {
                        string receiveLocationName = commandLineParser.GetDefaultValue("");
                        if (receiveLocationName.Length == 0)
                        {
                            ShowHelp();
                        }
                        else
                        {
                            if (commandLineParser.IsCommand("-d", "/d", "-disable", "/disable"))
                            {
                                if (choice == "-RL" ||choice == "-rl")
                                {
                                    RemoveRLServiceWindow(receiveLocationName);
                                }
                                if (choice == "-SP" ||choice == "-sp")
                                {
                                    RemoveSPServiceWindow(receiveLocationName);
                                }
                                if (choice == "-SS" || choice == "-ss")
                                {
                                    RemoveSSServiceWindow(receiveLocationName);
                                }
                            }
                            else if (commandLineParser.IsCommand("-q", "/q", "-query", "/query"))
                            {
                                if (choice == "-RL" ||choice == "-rl")
                                {
                                    Console.WriteLine("RL: {0}\n", receiveLocationName);
                                    Console.WriteLine(QueryRLServiceWindow(receiveLocationName));
                                }
                                else if (choice == "-SP" ||choice == "-sp")
                                {
                                    Console.WriteLine("SP: {0}\n", receiveLocationName);
                                     Console.WriteLine(QuerySPServiceWindow(receiveLocationName)); 
                                }
                                else if (choice == "-SS" || choice == "-ss")
                                {
                                    Console.WriteLine("SP: {0}\n", receiveLocationName);
                                    Console.WriteLine(QuerySSServiceWindow(receiveLocationName));
                                }
                            }
                            else
                            {
                                DateTime startTime;
                                DateTime endTime;
                                if (!DateTime.TryParse(commandLineParser.GetCommandValue("00:00", "-s:", "/s:", "-start:", "/start:"), out startTime))
                                {
                                    ShowHelp();
                                }
                                else if (!DateTime.TryParse(commandLineParser.GetCommandValue("00:00", "-e:", "/e:", "-end:", "/end:"), out endTime))
                                {
                                    ShowHelp();
                                }
                                else
                                {
                                    if (choice == "-RL" ||choice == "-rl")
                                    {
                                        Console.WriteLine("RL");
                                        SetRLServiceWindow(receiveLocationName, startTime, endTime);
                                    }
                                    else if (choice == "-SP" || choice =="-sp")
                                    {
                                        Console.WriteLine("SP: {0}", receiveLocationName);
                                        SetSendPortServiceWindow(receiveLocationName, startTime, endTime);
                                    }
                                    else if (commandLineParser.getChoice() == "-SS" ||choice == "-ss")
                                    {
                                        SetSendPortSecondayServiceWindow(receiveLocationName, startTime, endTime);
                                    }
                                   
                                }
                            }
                        }
                    }
                }
                Console.WriteLine("Done");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
#if DEBUG
            System.Threading.Thread.Sleep(500);

#endif
        }

        /// <summary>
        /// List all receive locations with a service window
        /// </summary>
        /// <returns>formatted test with list</returns>
        private static string ListRLWithServiceWindow()
        {
            string output = "Receive locations with service windows\r\n" + "Receive location".PadRight(60) + "\tStart\tEnd\r\n";
            List<string> lines = new List<string>();
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_ReceiveLocation, new ObjectGetOptions()))
            {
                foreach (ManagementObject obj in bts_AdminObjClass.GetInstances())
                {
                    if ((bool)obj["OperatingWindowEnabled"])
                    {
                        lines.Add(obj["Name"].ToString().PadRight(60) + "\t" +
                            ReadTime(obj["SrvWinStartDT"].ToString()) + "\t" +
                            ReadTime(obj["SrvWinStopDT"].ToString()));
                    }
                }
            }
            lines.Sort();
            lines.ForEach(delegate(string line) { output += line + "\r\n"; });
            return output;
        }
        private static string ListSPWithServiceWindow()
        {
            string output = "Send Port with service windows\r\n" + "Send Port:".PadRight(60) + "\tStart\tEnd\r\n";
            List<string> lines = new List<string>();
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                foreach (ManagementObject obj in bts_AdminObjClass.GetInstances())
                {
                    if ((bool)obj["PTServiceWindowEnabled"])
                    {
                        lines.Add(obj["Name"].ToString().PadRight(60) + "\t" +
                            ReadTime(obj["PTFromTime"].ToString()) + "\t" +
                            ReadTime(obj["PTToTime"].ToString()));
                    }
                }
            }
            lines.Sort();
            lines.ForEach(delegate(string line) { output += line + "\r\n"; });
            return output;
        }
        private static string ListSSWithServiceWindow()
        {
            string output = "Send Port with service windows\r\n" + "Send Port:".PadRight(60) + "\tStart\tEnd\r\n";
            List<string> lines = new List<string>();
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                foreach (ManagementObject obj in bts_AdminObjClass.GetInstances())
                {
                    if ((bool)obj["STServiceWindowEnabled"])
                    {
                        lines.Add(obj["Name"].ToString().PadRight(60) + "\t" +
                            ReadTime(obj["STFromTime"].ToString()) + "\t" +
                            ReadTime(obj["STToTime"].ToString()));
                    }
                }
            }
            lines.Sort();
            lines.ForEach(delegate(string line) { output += line + "\r\n"; });
            return output;
        }

        /// <summary>
        /// Queries the current value of the service window of the receive location
        /// </summary>
        /// <param name="receiveLocationName">Name of the receive location</param>
        /// <returns>Returns receive location service window details</returns>
        private static string QueryRLServiceWindow(string receiveLocationName)
        {
            string output = receiveLocationName;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_ReceiveLocation, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", receiveLocationName))
                {
                    if (appObject != null)
                    {
                        output += "\r\n  Enabled: " + appObject["OperatingWindowEnabled"].ToString();
                        output += "\r\n  Start  : " + ReadTime(appObject["SrvWinStartDT"].ToString());
                        output += "\r\n  Stop   : " + ReadTime(appObject["SrvWinStopDT"].ToString());
                    }
                    else
                    {
                        throw new Exception("Receive location " + receiveLocationName + " not found!");
                    }
                }
            }
            return output;
        }
        private static string QuerySPServiceWindow(string sendPorts)
        {
            string output = sendPorts;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace,bts_SendPort , new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", sendPorts))
                {
                    if (appObject != null)
                    {
                        output += "\r\n  Enabled: " + appObject["PTServiceWindowEnabled"].ToString();
                        output += "\r\n  Start  : " + ReadTime(appObject["PTFromTime"].ToString());
                        output += "\r\n  Stop   : " + ReadTime(appObject["PTToTime"].ToString());
                    }
                    else
                    {
                        throw new Exception("Send Port " + sendPorts + " not found!");
                    }
                }
            }
            return output;
        }
        private static string QuerySSServiceWindow(string sendPorts)
        {
            string output = sendPorts;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", sendPorts))
                {
                    if (appObject != null)
                    {
                        output += "\r\n  Enabled: " + appObject["STServiceWindowEnabled"].ToString();
                        output += "\r\n  Start  : " + ReadTime(appObject["STFromTime"].ToString());
                        output += "\r\n  Stop   : " + ReadTime(appObject["STToTime"].ToString());
                    }
                    else
                    {
                        throw new Exception("Send Port " + sendPorts + " not found!");
                    }
                }
            }
            return output;
        }

        /// <summary>
        /// Utility function to read raw WMI time string
        /// </summary>
        /// <param name="rawTime">raw time string</param>
        /// <returns>Time only portion of the string</returns>
        private static string ReadTime(string rawTime)
        {
            string output = "";
            if (rawTime.Length > 10)
            {
                output += rawTime.Substring(8, 2) + ":";
                output += rawTime.Substring(10, 2);
            }
            return output;
        }
        
        /// <summary>
        /// Remove(clear) service window of receive location
        /// </summary>
        /// <param name="receiveLocationName">Name of receive location</param>
        private static void RemoveRLServiceWindow(string receiveLocationName)
        {
            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOnly;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_ReceiveLocation, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", receiveLocationName))
                {
                    if (appObject != null)
                    {
                        appObject["OperatingWindowEnabled"] = false;
                        appObject.Put(options);
                    }
                    else
                    {
                        throw new Exception("Receive location " + receiveLocationName + " not found!");
                    }
                }
            }
        }
        private static void RemoveSPServiceWindow(string sendPortName)
        {
            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOnly;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", sendPortName))
                {
                    if (appObject != null)
                    {
                        appObject["PTServiceWindowEnabled"] = false;
                        appObject.Put(options);
                    }
                    else
                    {
                        throw new Exception("SendPort: " + sendPortName + " not found!");
                    }
                }
            }
        }
        private static void RemoveSSServiceWindow(string sendPortName)
        {
            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOnly;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", sendPortName))
                {
                    if (appObject != null)
                    {
                        appObject["STServiceWindowEnabled"] = false;
                        appObject.Put(options);
                    }
                    else
                    {
                        throw new Exception("SendPort: " + sendPortName + " not found!");
                    }
                }
            }
        }
        /// <summary>
        /// Set the times for the service window of the receive location
        /// </summary>
        /// <param name="receiveLocationName">Name of receive location</param>
        /// <param name="startTime">Start time</param>
        /// <param name="endTime">End time</param>
        private static void SetRLServiceWindow(string receiveLocationName, DateTime startTime, DateTime endTime)
        {
            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOnly;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_ReceiveLocation, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", receiveLocationName))
                {
                    if (appObject != null)
                    {
                        int offset = Convert.ToInt32(DateTime.Now.Subtract(DateTime.UtcNow).TotalMinutes);
                        string offsetStr = offset > 0 ? "+" + offset.ToString() : offset.ToString();

                        appObject["OperatingWindowEnabled"] = true;
                        appObject["SrvWinStartDT"] = "20100101" + startTime.ToString("HHmmss") + ".000000" + offsetStr; //DateTime.Parse("2000-1-1 " + startTime.ToString("HHmmss"));
                        appObject["SrvWinStopDT"] = "20100101" + endTime.ToString("HHmmss") + ".000000" + offsetStr; //DateTime.Parse("2000-1-1 " + endTime.ToString("HH:mm:ss"));
                        appObject.Put(options);
                    }
                    else
                    {
                        throw new Exception("Receive location " + receiveLocationName + " not found!");
                    }
                }
            }
        }
        private static void SetSendPortServiceWindow(string sendPortName, DateTime startTime, DateTime endTime)
        {
            Console.WriteLine("Entering SendPort Setting");
            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOnly;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", sendPortName))
                {
                    if (appObject != null)
                    {
                        int offset = Convert.ToInt32(DateTime.Now.Subtract(DateTime.UtcNow).TotalMinutes);
                        string offsetStr = offset > 0 ? "+" + offset.ToString() : offset.ToString();

                        appObject["PTServiceWindowEnabled"] = true;
              
                        appObject["PTFromTime"] = "20100101" + startTime.ToString("HHmmss") + ".000000" + offsetStr; //DateTime.Parse("2000-1-1 " + startTime.ToString("HHmmss"));
                        appObject["PTToTime"] = "20100101" + endTime.ToString("HHmmss") + ".000000" + offsetStr; //DateTime.Parse("2000-1-1 " + endTime.ToString("HH:mm:ss"));
                        appObject.Put(options);
                        Console.WriteLine("Success");
                    }
                    else
                    {
                        throw new Exception("Send Port: " + sendPortName + " not found!");
                    }
                }
            }
        }
        private static void SetSendPortSecondayServiceWindow(string sendPortName, DateTime startTime, DateTime endTime)
        {
         
            PutOptions options = new PutOptions();
            options.Type = PutType.UpdateOnly;
            using (ManagementClass bts_AdminObjClass = new ManagementClass(bts_WMINameSpace, bts_SendPort, new ObjectGetOptions()))
            {
                using (ManagementObject appObject = GetObject(bts_AdminObjClass, "Name", sendPortName))
                {
                    if (appObject != null)
                    {
                        int offset = Convert.ToInt32(DateTime.Now.Subtract(DateTime.UtcNow).TotalMinutes);
                        string offsetStr = offset > 0 ? "+" + offset.ToString() : offset.ToString();

                        appObject["STServiceWindowEnabled"] = true;
                       
                        appObject["STFromTime"] = "20100101" + startTime.ToString("HHmmss") + ".000000" + offsetStr; //DateTime.Parse("2000-1-1 " + startTime.ToString("HHmmss"));
                        appObject["STToTime"] = "20100101" + endTime.ToString("HHmmss") + ".000000" + offsetStr; //DateTime.Parse("2000-1-1 " + endTime.ToString("HH:mm:ss"));
                        appObject.Put(options);
                    
                    }
                    else
                    {
                        throw new Exception("Send Port: " + sendPortName + " not found!");
                    }
                }
            }
        }

        /// <summary>
        /// Check if WMI object with key and value exists
        /// </summary>
        /// <param name="objClass">host object</param>
        /// <param name="key">Key name</param>
        /// <param name="value">Value name</param>
        /// <returns>True is found</returns>
        private static bool ObjectExists(ManagementClass objClass, string key, string value)
        {
            foreach (ManagementObject obj in objClass.GetInstances())
            {
                if (obj[key].ToString() == value)
                    return true;
            }
            return false;
        }

        /// <summary>
        /// Get instance of WMI object with matching key and value
        /// </summary>
        /// <param name="objClass">host object</param>
        /// <param name="key">Key name</param>
        /// <param name="value">Value name</param>
        /// <returns>Matching WMI object</returns>
        private static ManagementObject GetObject(ManagementClass objClass, string key, string value)
        {
            foreach (ManagementObject obj in objClass.GetInstances())
            {
                if (obj[key].ToString() == value)
                    return obj;
            }
            return null;
        }

        private static void ShowHelp()
        {
            Console.WriteLine("Usage: BTSetSW.exe <-RL | -SP >  <receiveLocationName| Send Port>  <-l | <-s:<startTime> -e:<endTime> | -d | -q> >");
            Console.WriteLine(" Where");
            Console.WriteLine("  -RL       : To Set Service Window for Receive Location");
            Console.WriteLine("  -SP       : To set the service window of the primary transport for the send port");
            Console.WriteLine("  -l        : List all RL with service windows");
            Console.WriteLine("  startTime : Service window start time(eg: 09:00)");
            Console.WriteLine("  endTime   : Service window end time (eg: 23:00)");
            Console.WriteLine("  -d        : Remove/Delete service window");
            Console.WriteLine("  -q        : Query current service window");
            Console.WriteLine("Eg:Setting SendPort       : BTSetSW.exe -SP SendPortName -s:09:00 -e:21:00");
        }
    }
}
